import { Injectable } from "@nestjs/common";
import { LoginDto, LogOutDto } from "./dto/loginDto";
import { BodyDto, restBody } from "src/store/vo/BodyDto";
import { createMathExpr } from 'svg-captcha';
import { v4 as uuidv4 } from 'uuid';
import { VCodeVO } from "./interface/LoginVO";
import { LoginRepository } from "./login.repository";
import { ConfigService } from "@nestjs/config";
import { UserEntity } from "./entity/user.entity";
import { RedisCacheService } from "src/redis/redis.service";

@Injectable()
export class LoginService {

  constructor(
    private configService: ConfigService,
    private readonly loginRepository: LoginRepository,
    private readonly redisCacheService: RedisCacheService
  ) { }

  // 验证码数据
  private captchaMap = new Map<string, string>()

  /**
   * 生成验证码
   * @returns base64数据
   */
  async createVCode(): Promise<BodyDto<VCodeVO>> {
    const vcode = createMathExpr({
      width: 150,
      height: 40
    })
    const uuid = uuidv4()

    // 存储验证码
    this.captchaMap.set(uuid, vcode.text)

    // 设置验证码过期
    setTimeout(() => {
      this.captchaMap.delete(uuid)
    }, Number(this.configService.get('DATABASE_V_CODE')))

    return restBody({
      uuid,
      svgData: vcode.data
    })
  }

  /**
   * 查询指定组织下所有用户Id
   * @param orgId 组织Id
   * @returns 用户Ids
   */
  getOrgUserIds(orgId: number) {
    return this.loginRepository.getOrgUserIds(orgId)
  }

  /**
   * 登录接口
   * @param loginInfo 用户名密码
   * @returns 用户信息
   */
  async getUserInfo(loginInfo: LoginDto): Promise<UserEntity | null> {
    // 判断验证码是否正确
    if (
      !this.captchaMap.get(loginInfo.uuid)
      || (this.captchaMap.get(loginInfo.uuid) as string) !== loginInfo.authCode) {
      return Promise.reject('验证码不正确')
    }

    // 判断密码是否正确，返回用户信息
    const userData = await this.loginRepository.verifierPassword(loginInfo)

    if (userData === null) {
      return Promise.reject('用户名或密码错误')
    }

    // 查询用户菜单权限
    userData.menuList = await this.loginRepository.getMenuList(userData.roles)

    // 根据角色查询操作按钮权限
    userData.handleList = await this.loginRepository.getHandlePermission(
      userData.roles.map(item => item.id),
      userData.menuList.map(item => item.id)
    )

    // 返回用户信息
    return userData
  }

  /**
   * 退出登录
   * @param logoutDto 参数
   * @returns true or false
   */
  async logOut(logoutDto: LogOutDto): Promise<boolean | undefined> {

    // 删除token
    const num = await this.redisCacheService.delete([logoutDto.loginName + '_token'])

    return num ? true : false
  }
}